from bcat.util.str import Str

class ExpectTypeError(TypeError):
    def __init__(self, expect_type_msg, real_type_msg):
        super().__init__("expect type:[{}], but meet type:[{}]".format(expect_type_msg, real_type_msg))

    @staticmethod
    def from_real_type(expect_type, real_type):
        return ExpectTypeError(str(expect_type),  str(real_type))

    @staticmethod
    def from_real_value(expect_type, real_value):
        return ExpectTypeError(str(expect_type), str(type(real_value)))
        

class ExpectNumberLengthError(ValueError):
    def __init__(self, expect_len_msg, real_len_msg):
        super().__init__("expect int byte len:{}, but meet int byte len:{}".format(expect_len_msg, real_len_msg))

    @staticmethod
    def from_real_len(expect_byte_len, real_byte_len):
        return ExpectNumberLengthError(str(expect_byte_len), str(real_byte_len))


#baseclass for value error with message 
class NewValueError(ValueError):
    def __init__(self, msg="new Value Error"):
        super().__init__(msg)
        self.__msg = msg

    def message(self):
        return self.__msg

    def __str__(self):
        return self.__msg


class ValueEmptyError(NewValueError):
    def __init__(self, msg="Value Empty"):
        super().__init__(msg)

    def __str__(self):
        return super().__str__()

class ExpectLengthError(NewValueError):
    def __init__(self, expect, real):
        self.__expect = expect
        self.__real = real
        self.__msg = "expect:{}, but real:{}".format(self.__expect, self.__real)
        super().__init__(self.__msg)

    def __str__(self):
        return self.__msg







#base class for parse error
class ParseError(Exception):
    def __init__(self, offset, msg="Parse error"):
        self.__offset = offset
        self.__msg = msg

    def offset(self):
        return self.__offset

    def message(self):
        return self.__msg

    def __str__(self):
        return "offset:{}, error:{}" .format(self.offset(), self.message())


# internal use "offset:10, need:{}, error: {}"
class NeedSignError(ParseError):
    def __init__(self, sign, offset, msg=""):
        self.__sign = sign
        super().__init__(offset, msg)

    def sign(self):
        return self.__sign

    def __str__(self):
        s = "offset:[{}]".format(self.offset())

        if Str(self.sign()).is_not_empty():
            s += ", need {}".format(self.sign())

        if Str(self.message()).is_not_empty():
            s += ", error:{}".format(self.message())

        return s

class NeedCommaError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("comma:(,)", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedColonError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("colon:(:)", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedEqualSignError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("equal sign:(=)", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedOpenBracketsError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("open brackets:([)", offset, msg)

    def __str__(self):
        return super().__str__()
    
class NeedCloseBracketsError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("close brackets:(])", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedOpenBracesError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("open braces:({)", offset, msg)

    def __str__(self):
        return super().__str__()
    
class NeedCloseBracesError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("close braces:(})", offset, msg)

    def __str__(self):
        return super().__str__()
class NeedAlphaError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("alpha:(a~z, A~Z)", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedDigitError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("digit:(0~9)", offset, msg)

    def __str__(self):
        return super().__str__()

class NeedSlashError(NeedSignError):
    def __init__(self, offset, msg=""):
        super().__init__("slash:(\\)", offset, msg)

    def __str__(self):
        return super().__str__()

class UnescapeError(ParseError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, msg)
    
    def __str__(self):
        return super().__str__()

class PairEndError(ParseError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, msg)
    
    def __str__(self):
        return super().__str__()

class UnexpectEndOfStreamError(UnescapeError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, "unexpect end of stream" if msg is None or len(msg) == 0 else msg)
    
    def __str__(self):
        return super().__str__()
class NormalByteAfterEscapeError(UnescapeError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, "meet normal byte after escape sign" if msg is None or len(msg) == 0 else msg)
    
    def __str__(self):
        return super().__str__()
class InvalidSpecialByteError(UnescapeError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, "meet invalid special byte in bytes" if msg is None or len(msg) == 0 else msg)

    def __str__(self):
        return super().__str__()
class SpecialByteWithoutEscapeError(UnescapeError):
    def __init__(self, offset, msg=""):
        super().__init__(offset, "no escape slash for special byte" if msg is None or len(msg) == 0 else msg)

    def __str__(self):
        return super().__str__()
    


import unittest
class TestParseError(unittest.TestCase):
    def test_main(self):
        print(ParseError(10))
        print(NeedCommaError(20))
        print(NeedColonError(25))
        print(NeedOpenBracesError(30))
        print(NeedCloseBracesError(35))
        print(NeedOpenBracketsError(40))
        print(NeedCloseBracketsError(45))
        print(NeedEqualSignError(50))
        print(NeedSignError("comma(,) or close braces(})", 60))
